package words;

import java.util.HashMap;
import java.util.StringTokenizer;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.Map;
import java.util.Set;
import java.util.Iterator;

public class Annotation implements Comparable {

  // annotation tag Id
  int m_nId;

  // annotation span
  int m_nBegin;
  int m_nLen;

  // annotation attributes
  HashMap m_mapAtt;

  static Matcher m_match;
 
  static {
    Pattern pattern = Pattern.compile("([^=]+)=[\'\"]?([^=\'\"]+)[\'\"]?");
    m_match = pattern.matcher("");
  }
                                                                                
  public Annotation()
  {
    m_nId = -1;
    m_nBegin = -1;
    m_nLen = 0;
    m_mapAtt = new HashMap();
  }

  public Annotation(int nPos, int nLen)
  {
    m_nId = -1;
    m_nBegin = nPos;
    m_nLen = nLen;
    m_mapAtt = new HashMap();
  }

  public Annotation(TagDefinition tagDef, String strAnnotation,
		    int nPos, int nLen)
  {
    // read tag
    StringTokenizer strTok = new StringTokenizer(strAnnotation);
    m_nId = tagDef.getId(strTok.nextToken());

    // read attributes
    m_mapAtt = new HashMap();
    while (strTok.hasMoreTokens()) {
      String strAssign = strTok.nextToken();
      m_match.reset(strAssign);
      if (m_match.matches())
        m_mapAtt.put(m_match.group(1), m_match.group(2));
    }

    // compute span
    m_nBegin = nPos;
    m_nLen = nLen;
  }

  public int compareTo(Object o)
  {
    Annotation anno = (Annotation) o;
    if (m_nBegin < anno.m_nBegin)
      return -1;
    else if (m_nBegin == anno.m_nBegin) {
      if (m_nLen < anno.m_nLen)
        return -1;
      else if (m_nLen == anno.m_nLen)
        return 0;
    }
    
    return 1;
  }

  public boolean includes(Annotation anno)
  {
    return m_nBegin <= anno.m_nBegin && 
      m_nBegin + m_nLen >= anno.m_nBegin + anno.m_nLen;
  }

  public String toString()
  {
    StringBuffer sb = new StringBuffer();
    sb.append(String.valueOf(m_nId));
    sb.append(" = (");
    sb.append(String.valueOf(m_nBegin));
    sb.append(",");
    sb.append(String.valueOf(m_nLen));
    sb.append(")");

    Set entries = m_mapAtt.entrySet();
    Iterator eit = entries.iterator();
    while (eit.hasNext()) {
      Map.Entry entry = (Map.Entry) eit.next();
      String strKey = (String) entry.getKey();
      String strValue = (String) entry.getValue();
      sb.append(" " + strKey + "=" + strValue + " ");
    }

    return sb.toString();
  }

  public String getBegin(TagDefinition tagDef)
  {
    StringBuffer sb = new StringBuffer();
    sb.append("<");
    sb.append(tagDef.getName(m_nId));

    Set entries = m_mapAtt.entrySet();
    Iterator eit = entries.iterator();
    while (eit.hasNext()) {
      Map.Entry entry = (Map.Entry) eit.next();
      String strKey = (String) entry.getKey();
      String strValue = (String) entry.getValue();
      sb.append(" " + strKey + "=" + strValue);
    }
    sb.append(">");

    return sb.toString();
  }

  public String getEnd(TagDefinition tagDef)
  {
    StringBuffer sb = new StringBuffer();
    sb.append("</");
    sb.append(tagDef.getName(m_nId));
    sb.append(">");

    return sb.toString();
  }

  public String getAttribute(String strKey)
  {
    return (String) m_mapAtt.get(strKey);
  }

  public void setAttribute(String strKey, String strVal)
  {
    m_mapAtt.put(strKey, strVal);
  }

}
